package jude.java.money.provide;

import java.util.List;

public abstract class PagingProvider<T> extends BaseProvider<T> {
	public static final int PAGE_EOF = -3;
	
	protected int pageSize;
	protected int pageIndex;
	
	/** 是否页倒序获取数据 */
	private boolean reverse;
	/** 总页数 */
	protected int pageCount;
	/** 总记录数 */
	protected int totalCount;
	
	protected PagingProvider() {
		this(50, false);
	}
	
	protected PagingProvider(int pageSize) {
		this(pageSize, false);
	}
	
	protected PagingProvider(int pageSize, boolean reverse) {
		this.pageSize = pageSize;
		this.reverse = reverse;
		this.totalCount = -1;
	}
	
	@Override
	protected List<T> loadRecords() {
		return loadRecords(pageSize, pageIndex);
	}
	
	/**
	 * 页倒序获取时需要实现
	 * */
	protected int getTotalCount() {
		return 0;
	}
	
	private void setTotalCount(int totalCount) {
		this.totalCount = totalCount = Math.max(0, totalCount);
		this.pageCount = (totalCount - 1) / pageSize + 1;
		this.pageIndex = this.pageCount - 1;	//最后一页
	}
	
	protected abstract List<T> loadRecords(int pageSize, int pageIndex);
	
	@Override
	public synchronized T get() {
		if (stopped || recordIndex == EMPTY || recordIndex == EOF) {
			return null;
		}
		return reverse ? reverseGet() : normalGet();
	}
	
	private T normalGet() {
		if (recordIndex == PAGE_EOF) {
			records = loadRecords(pageSize, pageIndex);
			if (records == null || records.size() == 0) {
				if (recycle) {
					reset();
					return get();
				}
				recordIndex = EOF;
//				System.out.println("================================= " + pageIndex);
				return null;
			}
			recordCount += records.size();
			recordIndex = 0;
		} else if (records == null) {	//first time
			records = loadRecords(pageSize, pageIndex);
			if (records == null || records.size() == 0) {
				recordIndex = EMPTY;
//				System.out.println("++++++++++++++++++++++++++++++++++");
				return null;
			}
			recordCount += records.size();
		}
		int i = recordIndex;
		recordIndex ++;
		if (recordIndex == records.size()) {	//下一页
			pageIndex ++;
			recordIndex = PAGE_EOF;
		}
		provide ++;
		return records.get(i);
	}
	
	private T reverseGet() {
		if (totalCount == -1) {
//			System.out.println("\t\tsetTotalCount");
			setTotalCount(getTotalCount());
			if (totalCount == 0) {
				recordIndex = EMPTY;
				return null;
			}
		}
		if (recordIndex == PAGE_EOF) {
//			System.out.println("\t\tPAGE_EOF");
			records = loadRecords(pageSize, pageIndex);
			if (records == null || records.size() == 0) {
				if (pageIndex == 0) {
					if (recycle) {
						System.out.println("\t\tRECYCLE");
						reset();
						return get();
					}
					recordIndex = EOF;
					return null;
				}
				pageIndex --;
				System.out.println("\t\tCALLBACK");
				return get();			//not found, go previous
			}
			recordCount += records.size();
			recordIndex = 0;
		} else if (records == null) {	//first time
//			System.out.println("\t\tFIRSTTIME");
			records = loadRecords(pageSize, pageIndex);
			if (records == null || records.size() == 0) {
				recordIndex = EMPTY;
				return null;
			}
			recordCount += records.size();
		}
		provide ++;
		T o = records.get(recordIndex);
		recordIndex ++;
		if (recordIndex == records.size()) {	//下一页
//			System.out.println("\t\tNEXT PAGE");
			if (pageIndex == 0) {
				System.out.println("\t\tEND");
				if (recycle)
					reset();
				else
					recordIndex = EOF;
			} else {
				pageIndex --;
				recordIndex = PAGE_EOF;
			}
		}
//		System.out.println("\t\tRETURN");
		return o;
	}
	
	@Override
	public String getStatus() {
		if (reverse)
			return "xxxxx: " + provide + "/" + totalCount;
		return super.getStatus();
	}
	
	@Override
	public synchronized void reset() {
		super.reset();
		pageIndex = 0;
		recordIndex = 0;
		recordCount = 0;
		pageCount = 0;
		totalCount = -1;
	}
	
	public int getPageIndex() {
		return pageIndex;
	}
	
	public int getPageSize() {
		return pageSize;
	}
	
	public boolean isReverse() {
		return reverse;
	}
	
//	public int getPageCount() {
//		return total <= 0 ? -1 : ((total - 1)/pageSize + 1);
//	}
}
